package com.zbkj.admin.controller.merchant;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dtflys.forest.annotation.Post;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.query.QueryWrapper;
import com.zbkj.admin.listener.OrderCreateListener;
import com.zbkj.admin.mapper1.EbOrderMapper;
import com.zbkj.admin.mapper1.EbOrderProductVoucherRecordMapper;
import com.zbkj.admin.model.admin.SystemAdmin;
import com.zbkj.admin.model.order.Order;
import com.zbkj.admin.pojo.*;
import com.zbkj.admin.request.ArraignApplyRequest;
import com.zbkj.admin.response.EbDividendArraignResponse;
import com.zbkj.admin.service.*;
import com.zbkj.admin.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import net.dreamlu.mica.core.result.R;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.WebAsyncTask;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/// 积分管理模块
@Tag(name = "积分管理模块")
@RestController
@RequiredArgsConstructor
@RequestMapping({"/api/admin/points", "/api/front/points"})
public class PointsController {

    private final OrderService orderService;
    private final EbOrderMapper orderMapper;
    private final EbShopFlowingWaterService ebShopFlowingWaterService;
    private final EbDividendConfigService ebDividendConfigService;
    private final EbDividendArraignService ebDividendArraignService;
    private final EbDividendFlowingWaterService dividendFlowingWaterService;
    private final EbUserVoucherRecordService userVoucherRecordService;
    private final EbUserRelationshipService userRelationshipService;
    private final EbOrderProductVoucherRecordMapper ebOrderProductVoucherRecordMapper;

    /**
     * 根据ID查询用户层级关系
     *
     * @param id    用户ID
     * @param level 层级层数
     * @return 用户层级关系
     */
    @Operation(summary = "根据ID查询用户层级关系", description = "根据ID查询用户层级关系")
    @GetMapping("/{id}")
    public R<List<EbUserRelationshipEntity>> user(@PathVariable("id") Long id, @RequestParam("level") Integer level) {
        return R.success(userRelationshipService.threeLevelsUpward(id, level));
    }

    @Operation(summary = "计算期数")
    @GetMapping("/priceCount")
    public R<Dict> priceCount(@RequestParam("proportion") long proportion, @RequestParam("targetPeriod") int targetPeriod,
                              @RequestParam("initPrice") BigDecimal initPrice, @RequestParam("maxPeriod") Long maxPeriod) {
        return R.success(ebShopFlowingWaterService.priceCount(proportion, targetPeriod, initPrice, maxPeriod));
    }

    @GetMapping("/dividend")
    @Operation(summary = "计算当前商户下一期分红")
    public R<Boolean> dividend(@RequestParam(value = "isLimitationShop", required = false, defaultValue = "false") boolean isLimitationShop,
                               @RequestParam(value = "startData", required = false) LocalDateTime startData,
                               @RequestParam(value = "endData", required = false) LocalDateTime endData,
                               @RequestParam(value = "isWeek", required = false, defaultValue = "false") Boolean isWeek
    ) {
        startData = Objects.nonNull(startData) ? startData.withHour(0).withMinute(0).withSecond(0).withNano(0) : null;
        endData = Objects.nonNull(endData) ? endData.withHour(23).withMinute(59).withSecond(59) : null;
        if (Objects.nonNull(startData) && Objects.nonNull(endData) && isWeek) {
            Week week = DateUtil.dayOfWeekEnum(DateUtil.date(startData));
            if (week.equals(Week.MONDAY)) {
                startData = startData.minusDays(2);
            }
        }
        return ebShopFlowingWaterService.dividend(isLimitationShop, startData, endData);
    }

    @GetMapping("/countFlowingWater")
    public R<Dict> countFlowingWater() {
        Dict dict = new Dict(ebShopFlowingWaterService.countFlowingWater(false, null, null, null, it -> true));
        if (ObjUtil.isEmpty(dict)) {
            return R.fail("订单价格数据为空");
        }
        List<String> orderNo = dict.getBean("orderNoList");
        if (ObjUtil.isEmpty(orderNo)) {
            return R.fail("订单价格数据为空");
        }
        List<Order> orderList = new ArrayList<>();
        orderNo.forEach(it -> {
            Order byOrderNo;
            EbOrderEntity ebOrderEntity = orderMapper.selectOneByQuery(QueryWrapper.create()
                    .from(EbOrderEntity.class)
                    .where(EbOrderEntity::getOrderNo).eq(it)
            );
            if (Objects.nonNull(ebOrderEntity)) {
                byOrderNo = BeanUtil.copyProperties(ebOrderEntity, Order.class);
                orderList.add(byOrderNo);
            }
        });
        Map<Long, BigDecimal> ids = dict.getBean("ids");
        BigDecimal count = ids.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        List<EbOrderProductVoucherRecordEntity> recordEntities = ebOrderProductVoucherRecordMapper.selectAll();
        List<EbOrderProductVoucherRecordEntity> collect = recordEntities.stream().parallel().filter(it -> it.getIsEffective() == 0).collect(Collectors.toList());
        List<EbOrderProductVoucherRecordEntity> collected = recordEntities.stream().parallel().filter(it -> it.getIsEffective() == 1).collect(Collectors.toList());
        BigDecimal release = getCount(collected);
        BigDecimal notRelease = getCount(collect);
        BigDecimal reduce = orderList.stream().map(Order::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        return R.success(Dict.of().set("countOrderPrice", reduce).set("countPoints", count
                        .setScale(2, RoundingMode.HALF_UP).toPlainString())
                .set("release", release.setScale(2, RoundingMode.HALF_UP).toPlainString())
                .set("notRelease", notRelease.setScale(2, RoundingMode.HALF_UP).toPlainString())
        );
    }

    private BigDecimal getCount(List<EbOrderProductVoucherRecordEntity> recordEntities) {
        Map<Long, BigDecimal> collect1 = recordEntities.stream()
                .parallel().collect(Collectors.groupingBy(EbOrderProductVoucherRecordEntity::getUid,
                        OrderCreateListener.summingBigDecimal(it ->
                                it.getData().values().parallelStream().map(String::valueOf).map(BigDecimal::new)
                                        .reduce(BigDecimal.ZERO, BigDecimal::add))));
        return collect1.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @GetMapping("/page")
    @Operation(summary = "商户分红流水")
    public R<PageInfo<EbDividendRecordEntity>> page(Page<EbDividendRecordEntity> page,
                                                    @RequestParam(value = "shopName", required = false) String shopName,
                                                    @RequestParam(value = "state", required = false) Integer state,
                                                    @RequestParam(value = "startDate", required = false) LocalDateTime startDate,
                                                    @RequestParam(value = "endDate", required = false) LocalDateTime endDate) {
        return ebShopFlowingWaterService.page(page, shopName, state, startDate, endDate);
    }

    @GetMapping("/voucherPage")
    @Operation(summary = "抵用券流水")
    public R<PageInfo<EbUserVoucherRecordEntity>> voucherPage(Page<EbUserVoucherRecordEntity> page,
                                                              @RequestParam(value = "state", required = false) Integer state,
                                                              @RequestParam(value = "startDate", required = false) LocalDateTime startDate,
                                                              @RequestParam(value = "endDate", required = false) LocalDateTime endDate) {
        return userVoucherRecordService.page(page, state, startDate, endDate);
    }

    @GetMapping("/configPage")
    @Operation(summary = "抵用券额度")
    public R<BigDecimal> limit() {
        return userVoucherRecordService.limit();
    }

    @GetMapping("/arraignPage")
    @Operation(summary = "提现审批记录")
    public R<PageInfo<EbDividendArraignResponse>> arraignPage(Page<EbDividendArraignEntity> page,
                                                              @RequestParam(value = "examineAndApproveState", required = false) String examineAndApproveState,
                                                              @RequestParam(value = "startDate", required = false) LocalDateTime startDate,
                                                              @RequestParam(value = "endDate", required = false) LocalDateTime endDate) {
        return ebDividendArraignService.page(page, examineAndApproveState, startDate, endDate);
    }

    @GetMapping("/flowingWaterPage")
    @Operation(summary = "提现记录")
    public R<PageInfo<EbDividendFlowingWaterEntity>> flowingWaterPage(Page<EbDividendFlowingWaterEntity> page,
                                                                      @RequestParam(value = "startDate", required = false) LocalDateTime startDate,
                                                                      @RequestParam(value = "endDate", required = false) LocalDateTime endDate) {
        return dividendFlowingWaterService.page(page, startDate, endDate);
    }

    @GetMapping("/toExamine")
    @Operation(summary = "审批提现")
    public R<Boolean> toExamine(@RequestParam("id") Long id, @RequestParam("status") Integer status,
                                @RequestParam(value = "remarks", required = false) String remarks) {
        return ebDividendArraignService.toExamine(id, status, remarks);
    }

    @GetMapping("/getConfig")
    @Operation(summary = "获取审批配置")
    @Transactional(rollbackFor = Exception.class)
    public R<EbDividendConfigEntity> updateConfig() {
        SystemAdmin admin = SecurityUtil.getLoginUserVo().getUser();
        if (ObjUtil.isEmpty(admin)) {
            return R.fail("请先登录，后操作");
        }
        return R.success(ebDividendConfigService.getOne(ebDividendConfigService.from().where(EbDividendConfigEntity::getMerId).eq(admin.getMerId())));
    }

    @PutMapping("/updateConfig")
    @Operation(summary = "审批配置修改")
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> updateConfig(@RequestBody EbDividendConfigEntity config) {
        SystemAdmin admin = SecurityUtil.getLoginUserVo().getUser();
        if (ObjUtil.isEmpty(admin)) {
            return R.fail("请先登录，后操作");
        }
        config.setMerId(Long.valueOf(admin.getMerId()));
        ebDividendConfigService.updateById(config);
        return R.success(true);
    }

}
